<template>
    <div class="edit-video">
        <Header 
        :title="vodeoTitle"
        :tagList="tagList"
         @backClick="backClick"
         @inputChange="inputChange"
         ></Header>
    </div>
    <div class="content">
        <div class="select-people">
            <SmollTitle :label="'选择数字人'" />
            <SelectPeople @selectClick="selectClick"/>
        </div>
        <div class="show">
            <SmollTitle :label="'已选数字人'" />
            <img :src="peopleUrl" alt="">
        </div>
        <div class="txt">
            <SmollTitle :label="'话术设置'" />
            <Chat ref="chatRef" @select="selectChatType"/>
            <div  v-if="!chatType" class="line"></div>
            <div class="video" v-if="!chatType">
                    <span style="font-size: 14px;">选声音</span>
                    <div>
                        <div class="video-info">
                        <div class="info" @click="videoClick">
                            <el-icon v-if="Object.keys(audioSelectItem).length <= 0" style="cursor: pointer;"><Plus /></el-icon>
                            <img v-else :src="audioSelectItem?.type && audioIconList[audioSelectItem?.type] || audioIconList['WUMAN']" alt="">
                            <span  class="title" v-if="Object.keys(audioSelectItem).length <= 0">
                                请选择声音
                            </span>
                            <span v-else class="title">{{ audioSelectItem.name}}, {{audioSelectItem.description}}</span>
                        </div>
                        <div class="play-video" @click="playAudioAudition">
                            <div class="play">
                                <play-one v-if="palyVideo == 'pause'" class="icon" theme="multi-color" size="18" :fill="['#ccc' ,'#ccc' ,'#ccc' ,'#ccc']" />
                                <pause  v-if="palyVideo == 'play'" style="margin-top: 2px;" theme="filled" size="18" fill="#ccc" strokeLinecap="butt"/>
                                <LoadingOutlined v-else-if="palyVideo == 'loading'" style="font-size: 14px;font-weight: 600;"/>
                            </div>
                            <span>试听前30个字</span>
                        </div>
                    </div>
                    <div class="controll">
                        <div class="sigle-item" v-for="item in vedioControllList">
                            <span>{{item.label}}</span>
                                <el-slider 
                                class="pross_input" 
                                    v-model="item.value"
                                    :step="item.step"
                                    :max="item.max"
                                    :min="item.min"
                                />
                            <span class="nums">{{item.max}}</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>  
    </div>
    <div class="footer">
        <el-button :loading="btnLoading" color="#BC81FC" style="color: #292331;width: 80px;letter-spacing: 1px;" @click="createVideoClick">生成视频</el-button>
    </div>
    <Dialog 
        :show="showDialog" 
        :title="'选择声音'" 
        :width="600"
        :isCloseTip="false" 
        :is-custom-footer="false"
        @on-close="showDialog = false;audioPlayer && audioPlayer.pause();audioSource = ''"
        @on-sure-click="showDialog = false; audioPlayer && audioPlayer.pause();audioSource = ''"
    >
        <template #content>
            <div class="audio-list">
                <audio ref="audioPlayer" :src="audioSource" @loadeddata="loadeddate"  @ended="onendedNew"></audio>
                <div class="mine">
                    <h4>我的声音</h4>
                    <div class="audio">
                        <div :class="{'audio-item': true, 'audio-item__active':audioSelectType == 'mine' && item.name == audioSelectItem.name}" v-for="(item, index) in audioList.mineList" @click="audioSelectClick(item, 'mine')">
                            <img :src="item?.type && audioIconList[item?.type] || audioIconList['WUMAN']" alt="" >
                            <span class="title">{{ item.name }}, {{item.description}}</span>
                            <div class="play"  @click="auditionAudioPlayClick(item, index, 'mine')">
                                <play-one v-if="item.play == 'pause'" class="icon" theme="multi-color" size="10" :fill="['#ccc' ,'#ccc' ,'#ccc' ,'#ccc']"/>
                                <pause v-else-if="item.play == 'play'" theme="multi-color" style="margin-top: 4px;" size="10" :fill="['#ccc' ,'#ccc' ,'#ccc' ,'#ccc']"/>
                                <LoadingOutlined v-else-if="item.play == 'loading'"  style="font-size: 14px;font-weight: 600;"/>

                            </div>
                        </div>
                    </div>
                </div>
                <div class="public">
                    <h4>公共声音</h4>
                    <el-tabs type="border-card" v-model="actvieAudioType" class="video-tabs">
                        <el-tab-pane :label="tab.label" :name="tab.value" v-for="tab in audioTypeTabList"></el-tab-pane>
                    </el-tabs>
                    <div class="audio">
                        <div :class="{'audio-item': true, 'audio-item__active': audioSelectType == 'public' && item.name == audioSelectItem.name}" v-for="(item, i_index) in audioList.publicList.filter(val => val.scene == actvieAudioType)" @click="audioSelectClick(item, 'public')">
                            <img :src="item?.type && audioIconList[item?.type] || audioIconList['WUMAN']" alt="">
                            <span class="title">{{ item.name }}, {{item.description}}</span>
                            <div class="play"  @click="auditionAudioPlayClick(item, i_index, 'public')">
                                <play-one v-if="item.play == 'pause'" class="icon" theme="multi-color" size="10" :fill="['#ccc' ,'#ccc' ,'#ccc' ,'#ccc']"/>
                                <pause v-else-if="item.play == 'play'" theme="multi-color" style="margin-top: 4px;" size="10" :fill="['#ccc' ,'#ccc' ,'#ccc' ,'#ccc']"/>
                                <LoadingOutlined v-else-if="item.play == 'loading'" style="font-size: 14px;font-weight: 600;" />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </template>
    </Dialog>
  
</template>
<script setup lang="ts">
import { PlayOne, Pause } from '@icon-park/vue-next'
import { LoadingOutlined } from '@ant-design/icons-vue';
import SelectPeople from '@/components/selectPeople/index.vue'
import Chat from '@/components/chat/chat.vue'
import SmollTitle from '@/components/smollTitle/smollTitle.vue'
import Header from '@/components/header/header.vue'
import Dialog from '@/components/dialog/dialog.vue'
import {getMineAudioList, getPublicAudioList, getAudioStream, createVideo} from '@/service/video'
import { AudioInfo } from '@/models/home/video'
import {to} from 'await-to-js'
import {useRouter} from 'vue-router'
import {reactive, ref, onUnmounted} from 'vue'
import {ElMessage} from 'element-plus'
import { useVideoStore } from '@/store/video';
import { Plus,Close } from '@element-plus/icons-vue';
const router = useRouter();
const store = useVideoStore();
const palyVideo = ref<string>('pause')
const peopleUrl = ref<string>('')
const vodeoTitle = ref<string>('')
const tagList = ref<string[]>([])
const showDialog = ref<boolean>(false)
const audioSource = ref<string>('')
const selectPeopleId = ref<string | number>('')
const chatRef = ref(null)
const playVideoIndex = ref<number | string>('') // 播放声音的坐标
const audioContext = ref<any>()
const audioIconList: { [key: string]: string} = {
    GRIL: 'https://img.alicdn.com/tfs/TB1NW9ZDMDqK1RjSZSyXXaxEVXa-516-516.png',
    MAN: 'https://img.alicdn.com/tfs/TB1Ek54DPTpK1RjSZKPXXa3UpXa-517-517.png',
    WUMAN: 'https://img.alicdn.com/tfs/TB1Ij98DQPoK1RjSZKbXXX1IXXa-517-517.png',
    BOY: 'https://img.alicdn.com/tfs/TB1WCzHbjMZ7e4jSZFOXXX7epXa-238-238.png'
}
const vedioControllList = ref<any[]>([
    {key: 'volume',label: '音量', step: 1 , max: 100, min: 0, value: 50},
    {key: 'tone', label: '音调', step: 10 , max: 500, min: -500, value: 0},
    {key: 'speed', label: '语速', step: 10 , max: 500, min: -500, value: 0}
])
const btnLoading = ref<boolean>(false)
const audioPlayer = ref(null);
const audioList = reactive<{
    mineList: AudioInfo[],
    publicList: AudioInfo[]
}>({
    mineList: [],
    publicList: []
})
const audioSelectItem = ref<AudioInfo>({})
const audioSelectType = ref<string>('')
const playAudioSelectType =  ref<string>('');
// const playAudioSouce =  ref<string>('');
const chatType = ref<number>(0)
const actvieAudioType= ref<string>('COMMON')
const audioTypeTabList = ref<any[]>([
    {label: '通用', value: 'COMMON'},
    {label: '数字人', value: 'DIGITAL_MAN'},
    {label: '多情感', value: 'MULTI_EMOTION'},
    {label: '客服', value: 'CUSTOMER_SERVICE'},
    {label: '文学', value: 'LITERATURE'},
    {label: '高清', value: 'HD'},
    {label: '直播', value: 'LIVE'},
    {label: '童声', value: 'CHILD'},
    {label: '多语种', value: 'MULTI_LAN'},
    {label: '英文', value: 'ENG'},
    {label: '方言', value: 'DIALECT'},
])
const backClick = () => {
    router.back();
    store.setIsList(true)
}
// 选择声音
const videoClick = async () => {
    showDialog.value = true;
    await getMineAudioListData();
    await getPublicAudioListData();
}
// const auditionAudioClick = () => {

// }
// 加载完成后播放
const loadeddate = () => {
    let publicList = audioList.publicList.filter(res => actvieAudioType.value == res.scene)
    if(playAudioSelectType.value == 'mine') {
        audioList.mineList[Number(playVideoIndex.value)].play = 'play';
    }
    if(playAudioSelectType.value == 'public') {
        publicList[Number(playVideoIndex.value)].play = 'play';
    }
    audioPlayer.value && audioPlayer.value.play();
}

// 播放完成后设置暂停
const onendedNew = () => {
    let publicList = audioList.publicList.filter(res => actvieAudioType.value == res.scene)
    if(playAudioSelectType.value == 'mine') {
        audioList.mineList[Number(playVideoIndex.value)].play = 'pause';
    }
    if(playAudioSelectType.value == 'public') {
        publicList[Number(playVideoIndex.value)].play = 'pause';
    }
}
// 试听声音
const auditionAudioPlayClick =  (item: any, index: number, type: string) => {
    if(!item.auditionUrl) {
        ElMessage.error('播放错误，没有获取到音频文件')
        return;
    }
    let publicList = audioList.publicList.filter(res => actvieAudioType.value == res.scene)

    // 如果本次点击和上次一样  只需要直接播放暂停
    if(audioSource.value !== '' &&  audioSource.value == item.auditionUrl) {
        if(audioPlayer.value && audioPlayer.value.paused) {
            if(type == 'mine') {
            audioList.mineList[index].play = 'play';
            }
            if(type == 'public') {
                publicList[index].play = 'play';
            }
            audioPlayer.value && audioPlayer.value.play();

        }else {
            if(type == 'mine') {
            audioList.mineList[index].play = 'pause';
            }
            if(type == 'public') {
                publicList[index].play = 'pause';
            }
            audioPlayer.value && audioPlayer.value.pause();
        }
        playVideoIndex.value = index;
        playAudioSelectType.value = type;
        return;
    }
    // 如果选过的  需要把之前的先暂停
    if(audioSource.value !== '' && audioSource.value !== item.auditionUrl ) {
        if(type == 'mine') {
        // if()pause
        audioList.mineList[Number(playVideoIndex.value)].play = 'pause';
        audioList.mineList[index].play = 'loading';
        }
        if(type == 'public') {
            publicList[Number(playVideoIndex.value)].play = 'pause';
            publicList[index].play = 'loading';
        }
        audioSource.value = item.auditionUrl;
        playVideoIndex.value = index;
        playAudioSelectType.value = type;
        return;
    }
    // 第一次选择播放的时候 直接设置加载
    if(audioSource.value == ''  ||  audioSource.value !== item.auditionUrl) {
        if(type == 'mine') {
        // if()
        audioList.mineList[index].play = 'loading';
        }
        if(type == 'public') {
            publicList[index].play = 'loading';
        }
        audioSource.value = item.auditionUrl;
        playVideoIndex.value = index;
        playAudioSelectType.value = type;
        return;
    }
}
// 选择数字人
const selectClick = ({url, id}: {url: string, id: string | number}) => {
    peopleUrl.value = url
    selectPeopleId.value = id;
}
// 修改标签或者标题
const inputChange = ({label, type}: {label: string, type: string}): void => {
    if(type == 'title') {
        vodeoTitle.value = label;
    }else if (type == 'tag') {
        tagList.value.push(label)
    }else {
        tagList.value.splice(tagList.value.indexOf(label), 1)
    }
}
//获取我的声音
const getMineAudioListData = async() => {
    const [err, res] = await to(getMineAudioList())
    if(err || !res.success){
        return;
    }
    audioList.mineList = res?.items.map((res: any) => ({...res, play: 'pause'})) || []
}
// 获取公共的声音
const getPublicAudioListData = async() => {
    const [err, res] = await to(getPublicAudioList())
    if(err || !res.success){
        return;
    }
    audioList.publicList = res?.items.map((res: any) => ({...res, play: 'pause'})) || []
}

const audioSelectClick = (item: AudioInfo, type: string) => {
    audioSelectItem.value = item;
    audioSelectType.value = type;
}
// 播放声音
const playVideo = (): void => {
   if( playVideo.value == 'play') {

   }
    // audioPlayer.value.play();
}
// const pauseVideo = (): void => {
// }
// 试听
const playAudioAudition = async(): Promise<void> => {
    if(Object.keys(audioSelectItem.value).length <= 0) {
        ElMessage.error('请选择声音')
        return;
    }
    const info = vedioControllList.value.reduce((acc, curr) => {
        acc[curr.key] = curr.value;
        return acc;
    }, {})
    if(!chatRef.value || !chatRef.value?.text) {
        ElMessage.error('请输入文本')
        return;
    }
    if(audioContext.value) {
        if (audioContext.value.state === "running") {
            palyVideo.value = 'pause';
            audioContext.value.suspend();
           
        } else if (audioContext.value.state === "suspended") {
            palyVideo.value = 'play'
            audioContext.value.resume();
        }
        return;
    }
    palyVideo.value = 'loading';
    const [err, res] = await to(getAudioStream({
        voiceId: audioSelectItem.value.id,
        text: chatRef.value.text.slice(0, 30),
        ...info
    }))
    if(err) {
        ElMessage.error('播放错误')
        return;
    }
    let reader = new FileReader();
    audioContext.value = new window.AudioContext()
    reader.onload= (evt) => {
        if(evt.target?.readyState === FileReader.DONE) {
            const result = evt.target?.result;
            if (result instanceof ArrayBuffer) {
                audioContext.value.decodeAudioData(result, (buffer: any) => {
                   const audioBufferSouceNode = audioContext.value.createBufferSource();
                    audioBufferSouceNode.buffer =  buffer;
                    audioBufferSouceNode.connect(audioContext.value.destination);
                    // 开始播放
                    palyVideo.value = 'play';
                    audioBufferSouceNode.start(0);
                    // 监听播放完成事件
                    audioBufferSouceNode.onended = () => {
               
                        audioContext.value = null;
                        palyVideo.value = 'pause';
                    };
                }, (e: any) => {
                    console.log(e);
                });
            } else {
                console.log("不是 ArrayBuffer 类型");
            }
        }
    }
    reader.readAsArrayBuffer(res);
}

const createVideoClick = async() => {
    if(!vodeoTitle.value) {
        ElMessage.error('请输入标题')
        return;
    }
    // if(tagList.value.length == 0) {
    //     ElMessage.error('请设置标签')
    //     return;
    // }
    
    if(!selectPeopleId.value) {
        ElMessage.error('请选择数字人')
        return;
    }
    if(!chatRef.value || (!chatRef.value?.text && !chatRef.value?.fileList.length)) {
        ElMessage.error('请输入文本或者上传文件')
        return;
    }
    if(chatType.value == 0 && !audioSelectItem.value.id) {
        ElMessage.error('请选择声音');
        return;
    }
    let form = new FormData();
    form.append('title', vodeoTitle.value);
    form.append('tags',  tagList.value && tagList.value?.join(',') || '')
    form.append('avatarId', selectPeopleId.value)
    form.append('audioType', chatType.value == 0  ? 'AI': 'UPLOAD')
    if(chatType.value == 0 ) {
        form.append('voiceId', audioSelectItem.value && audioSelectItem.value.id)
    }
    vedioControllList.value.forEach(res => {
        form.append(res.key, res.value); 
    })
    if(chatRef.value.fileList.length > 0) {
        form.append('audioFile', chatRef.value.fileList[0].raw)
    }else {
        form.append('text', chatRef.value?.text)
    }
    btnLoading.value = true;
    const [err, res] = await to(createVideo(form));
    btnLoading.value = false;
    if(err || !res.success) {
        ElMessage.error(`请求错误${res.message}`)
        return;
    }
    ElMessage.success(`创建成功`)
    router.back();
    store.setIsList(true)
}
const selectChatType = (e: number) => {
    chatType.value  =  e;
}
onUnmounted(() => {
    // audioPlayer.value.removeEventListener('canplaythrough', playVideo)
})

</script>

<style scoped lang="css">
.edit-video{
    color: #fff;
}
.content {
    padding-top: 20px;
    display: flex;
}
.select-people{
    flex: 1;
    width: 200px;
    height: 73vh;
    background: #25212B;
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    box-sizing: border-box;
    padding: 0 10px;
}

.show {
    color: #fff;
    margin:0 20px;
    flex: 2;
    background: #25212B;
    border-radius: 10px;
    display: flex;
    align-items: center;
    flex-direction: column;
    height: 73vh;
}
.show >img {
    height: 400px;
    margin-top: 100px;
    box-sizing: border-box;
}
.txt {
    flex: 3;
    background: #25212B;
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    box-sizing: border-box;
    height: 73vh;
}
.line {
    height: 1px;
    margin-left: 60px;
    width: 82%;
    background-color: #38343C;
}

.video {
    width: 92%;
    display: flex;
    color: #FFF;
    margin-top: 20px;
    align-items: center;
    height: 18vh;
    /* align-items: center; */
}
.video > span {
    display: flex;
    width: 60px;
    margin-right: 10px;
    font-size: 16px !important;
}
.video-info {
    display: flex;
    align-items: center;
    margin-bottom: 2vh;
}
.play-video {
    margin-left: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    font-size: 12px;
}
.play-video > span {
    margin-top: 2px;
    text-align: center;
    display: flex;
    cursor: pointer;
}
.play{ 
    /* padding: 10px; */
    width: 30px;
    height: 30px;
    /* margin-left: 20px; */
    border-radius: 50%;
    background-color: #BC81FC;
    display: flex;
    align-items: center;
    justify-content: center;
    color: skyblue;
    cursor: pointer;
}
.play > .icon {
    margin-top: 4px;
}
.info {
    /* width: ; */
    flex: 1;
    height: 48px;
    padding: 0 10px;
    border:  1px solid salmon;
    display: flex;
    align-items: center;
    width: 250px;
    cursor: pointer;
}
.info >img {
    width: 30px;
    height: 30px;
    cursor: pointer;
}
.info .title {
    font-size: 12px;
    margin-left: 10px;
    color: #fff;
}
.sigle-item{ 
    width: 440px;
    display: flex;
    align-items: center;
}
.sigle-item span {
    font-size: 12px;
}
.sigle-item .pross {
    width: 360px;
    position: relative;
    height: 4px;
    background: #DBDBDB;
    border-radius: 10px;
    margin:0 15px;
}
:deep(.el-slider__bar, .el-slider__button) {
    background: salmon;
}
:deep(.el-slider__button) {
    border: 2px solid salmon;
    width: 15px;
    height: 15px;
}
/* .pross > .inner {
    position: absolute;
    left: 0;
    width: 100px;
    background-color: #8252B3;
    top: 0;
    height: 4px;
}
.pross > .ball {
    width: 8px;
    height: 8px;
    top: -2px;
    border-radius: 50%;
    background-color: #8252B3;
    position: absolute;
    left: 98px;
} */
/* input[type="range" i]::-webkit-slider-container{
    height: 4px;
    background: #eee;
} */
.pross_input{
    border-radius: 10px;
    width: 350px;
    margin: 0 10px;
}

.footer {
    width: 100%;
    background: #25212B;
    margin-top: 20px;
    border-radius: 10px;
    height: 6vh;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    box-sizing: border-box;
    padding-right: 2vw;
    /* padding: 2vh; */
}
/* :deep(.footer > .el-button) {
    
} */
:deep(.el-button .el-button--primary) {
    color: #8252B3 !important;
}
.audio-list {
    height: 66vh;
    color: #fff;
    overflow: auto;
}
.audio-list::-webkit-scrollbar {
    display: none;
}
.audio-list  h4 {
    padding-bottom: 8px;
    border-bottom: 1px solid #eee;
}
.mine {
    margin-bottom: 20px;
}
.video-tabs {
    margin-bottom: 10px;
}
.audio {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
}

.audio-item {
    padding: 8px 10px;
    display: flex;
    align-items: center;
    border:  1px solid salmon;
    width: 240px;
    position: relative;
    /* margin-right: 10px; */
    border-radius: 4px;
    margin-top: 10px;
    cursor: pointer;
}
.audio-item:hover {
    color: salmon;
    background-color: #FFF9F5;
}
.audio-item__active {
    color: salmon;
    background-color: #FFF9F5;
}
.audio-item .play{
    display: none;
    width: 24px;
    height: 24px;
    background-color: rgba(0, 0, 0, 0.5);
   
}
.audio-item > img {
    width: 24px;
    height: 24px;
}
.audio-item:hover .play {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    top: 8px;
    left: 10px;
    cursor: pointer;

}
.audio-item > span {
    margin-left: 10px;
}
:deep(.el-radio__input.is-checked .el-radio__inner) {
    background: #8252B3 !important;
    border-color: #8252B3 !important;
}
:deep(.el-tabs__content) {
    padding: 0;
}
:deep(.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active){
     color: #FA8072;
     border-left:1px solid #000;
     border-right:1px solid #000;
     border-bottom: 2px solid #FA8072;
     background: #000;
}
:deep(.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover) {
    color: #fff;
}
:deep(.el-tabs--border-card>.el-tabs__header) {
    border: 0;
}
:deep(.el-tabs--border-card>.el-tabs__header) {
    background-color: #000;
    color: #fff;
}
:deep(.el-tabs__item){
    color: #fff;
}
:deep(.el-tabs--border-card) {
    border: 0;
}
</style>